import 'package:casdon/modules/lifeCircle/domain/states/life_topic_comment_list_state.dart';
import 'package:casdon/modules/lifeCircle/providers/life_provider.dart';
import 'package:casdon/modules/lifeCircle/data/repository/life_repository_impl.dart';
import 'package:casdon/core/network/api_client_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class LifeTopicCommentListNotifier
    extends FamilyAsyncNotifier<LifeTopicCommentListState, String> {
  late String topicId;
  final int _pageSize = 10;
  bool _isRefreshing = false;
  KeepAliveLink? _keepAliveLink;
  final Map<String, DateTime> _likeDebounce = {};
  static const _likeDebounceDuration = Duration(milliseconds: 800);

  @override
  Future<LifeTopicCommentListState> build(String arg) async {
    topicId = arg;
    ref.onDispose(() {
      _keepAliveLink?.close();
      _keepAliveLink = null;
    });
    _keepAliveLink ??= ref.keepAlive();

    final fresh = await _fetchData(page: 1);
    _updateKeepAlive(fresh);
    return fresh;
  }

  Future<void> refresh() async {
    await _refreshSilently(force: true);
  }

  Future<LifeTopicCommentListState> _fetchData({required int page}) async {
    final response = await ref
        .read(lifeTopicCommentListUsecaseProvider)
        .execute(topicId: topicId, pageNum: page, pageSize: _pageSize);
    final rows = response.rows ?? const [];
    final items = rows.map(LifeTopicCommentViewData.fromApi).toList();
    final consumed = (page - 1) * _pageSize + rows.length;
    final hasMore = response.total > 0
        ? consumed < response.total
        : rows.length >= _pageSize;

    return LifeTopicCommentListState(
      comments: items,
      totalSize: response.total,
      page: page,
      pageSize: _pageSize,
      isLoadingMore: false,
      hasMore: hasMore,
    );
  }

  Future<void> loadMore() async {
    final current = state.valueOrNull;
    if (current == null || current.isLoadingMore || !current.hasMore) return;
    state = AsyncValue.data(current.copyWith(isLoadingMore: true));

    try {
      final nextPage = current.page + 1;
      final nextState = await _fetchData(page: nextPage);
      final merged = current.copyWith(
        comments: [...current.comments, ...nextState.comments],
        page: nextPage,
        totalSize: nextState.totalSize,
        hasMore: nextState.hasMore,
        isLoadingMore: false,
      );
      state = AsyncValue.data(merged);
      _updateKeepAlive(merged);
    } catch (e) {
      state = AsyncValue.data(current.copyWith(isLoadingMore: false));
      debugPrint('Load more comments error: $e');
    }
  }

  Future<void> _refreshSilently({bool force = false}) async {
    if (_isRefreshing) return;
    _isRefreshing = true;
    final previous = state.valueOrNull;
    try {
      final fresh = await _fetchData(page: 1);
      state = AsyncValue.data(fresh);
      _updateKeepAlive(fresh);
    } catch (e, st) {
      if (previous == null) {
        state = AsyncValue.error(e, st);
      } else if (force) {
        state = AsyncValue.data(previous);
        _updateKeepAlive(previous);
      }
    } finally {
      _isRefreshing = false;
    }
  }

  void _updateKeepAlive(LifeTopicCommentListState data) {
    if (data.comments.isNotEmpty) {
      _keepAliveLink ??= ref.keepAlive();
    } else {
      _keepAliveLink?.close();
      _keepAliveLink = null;
    }
  }

  Future<void> toggleLike(String commentId) async {
    final now = DateTime.now();
    final last = _likeDebounce[commentId];
    if (last != null && now.difference(last) < _likeDebounceDuration) {
      return;
    }
    _likeDebounce[commentId] = now;

    final current = state.valueOrNull;
    if (current == null) return;

    LifeTopicCommentViewData? target;
    void find(List<LifeTopicCommentViewData> list) {
      for (final c in list) {
        if (c.id == commentId) {
          target = c;
          return;
        }
        if (c.replies.isNotEmpty) find(c.replies);
        if (target != null) return;
      }
    }

    find(current.comments);
    if (target == null) return;

    final bool newLiked = !target!.isLiked;
    final int newCount = newLiked
        ? target!.likeCount + 1
        : (target!.likeCount > 0 ? target!.likeCount - 1 : 0);
    final updatedComments = _updateCommentTree(
      current.comments,
      commentId,
      newLiked,
      newCount,
    );

    state = AsyncValue.data(current.copyWith(comments: updatedComments));

    try {
      final repo = LifeRepositoryImpl(apiClient: ref.read(apiClientProvider));
      await repo.likeTopic(id: commentId, type: 1, flag: newLiked ? 1 : 0);
    } catch (e) {
      // revert on failure
      final revertComments = _updateCommentTree(
        current.comments,
        commentId,
        target!.isLiked,
        target!.likeCount,
      );
      state = AsyncValue.data(current.copyWith(comments: revertComments));
      debugPrint('Like comment failed: $e');
    }
  }

  List<LifeTopicCommentViewData> _updateCommentTree(
    List<LifeTopicCommentViewData> list,
    String id,
    bool newLiked,
    int newCount,
  ) {
    return list.map((c) {
      if (c.id == id) {
        return c.copyWith(isLiked: newLiked, likeCount: newCount);
      }
      if (c.replies.isNotEmpty) {
        return c.copyWith(
          replies: _updateCommentTree(c.replies, id, newLiked, newCount),
        );
      }
      return c;
    }).toList();
  }
}
